package info.nixbear.tgcms.user;

import info.nixbear.tgcms.domain.Attachment;
import info.nixbear.tgcms.domain.Page;
import info.nixbear.tgcms.domain.Redirect;
import info.nixbear.tgcms.services.dao.AttachmentDao;
import info.nixbear.tgcms.services.dao.EntityDao;
import info.nixbear.tgcms.services.dao.PageDao;
import info.nixbear.tgcms.services.dao.appengine.AppengineAttachmentDao;
import info.nixbear.tgcms.services.dao.appengine.AppengineEntityDao;
import info.nixbear.tgcms.services.dao.appengine.AppenginePageDao;

import java.io.IOException;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;

import com.google.appengine.api.blobstore.BlobKey;
import com.google.appengine.api.images.Image;
import com.google.appengine.api.images.ImagesService;
import com.google.appengine.api.images.ImagesServiceFactory;
import com.google.appengine.api.images.Transform;

public class RouterServlet extends HttpServlet {

	EntityDao<Redirect> redirectDao = new AppengineEntityDao<Redirect>(Redirect.class);
	PageDao pageDao = new AppenginePageDao();

	private static final long serialVersionUID = -1999885731327138730L;

	VelocityContext context = new VelocityContext();
	Pattern imageWithSize = Pattern.compile("^(.*)/([shw])(\\d+)/([^/.]*).([^/]*)$");

	public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
		boolean debug = "debug=true".equals(req.getQueryString());

		String uriString = req.getRequestURI().toString();

		String url = uriString.replaceAll("/$", "").replaceAll("^/", "");
		if (url.isEmpty()) {
			url = "index.html";
		}

		String fullUrl = (req.getQueryString() != null) ? (req.getRequestURI() + "?" + req
				.getQueryString()) : req.getRequestURI();

		List<Redirect> redirects = redirectDao.listAll();
		if (redirects != null) {
			for (Redirect redirect : redirects) {
				if (redirect.getFromUrl() != null && 
						redirect.getToUrl() != null &&
						fullUrl.matches(redirect.getFromUrl())) {
					Pattern pattern = Pattern.compile(redirect.getFromUrl());
					Matcher matcher = pattern.matcher(fullUrl);
					String redirectUrl = redirect.getToUrl();
					if (matcher.find()) {
						for (int i = 0; i < matcher.groupCount(); i++) {
							redirectUrl = redirectUrl.replace("{" + i + "}", matcher.group(i + 1));
						}
					}
					resp.sendRedirect(redirectUrl);
					return;
				}
			}
		}

		Page page = pageDao.findByUrl(url);
		
		if(debug) {
			resp.getWriter().println("Url: "+url);
			resp.getWriter().println("Page: "+page);
			if(page != null) {
				resp.getWriter().println("Page.getTemplate(): "+page.getTemplate());
			}
		}

		if (page == null || page.getTemplate() == null) {
			AttachmentDao attachmentDao = new AppengineAttachmentDao();
			Attachment attachment = attachmentDao.findByUrl(url);

			if(debug) {
				resp.getWriter().println("Attachment: "+attachment);
				if(attachment != null) {
					resp.getWriter().println("Attachment.getTemplate(): "+attachment.getTemplate());
				}
			}
			
			if (attachment != null && attachment.getTemplate() != null) {

				resp.setContentType((attachment.getTemplate().getContentType() == null || attachment
						.getTemplate().getContentType().isEmpty()) ? "text/html; charset=utf-8"
						: attachment.getTemplate().getContentType());

				context.put("page", attachment);

				Velocity.evaluate(context, resp.getWriter(), "log tag name", attachment
						.getTemplate().getHtmlAsString());
				return;
			} else {
				Matcher matcher = imageWithSize.matcher("/" + url);
				if (matcher.find()) {
					String url2 = url.substring(0,
							url.length() - matcher.group(3).length() - matcher.group(4).length() -
							matcher.group(5).length()- 3)
							+ matcher.group(4) + ".html";
					if(debug) {
						resp.getWriter().println("Found. Url2: "+url2);
					}
					
					Attachment attachment2 = attachmentDao.findByUrl(url2);

					if(debug) {
						resp.getWriter().println("Attachment2: "+attachment2);
						if(attachment2 != null) {
							resp.getWriter().println("Attachment2.getTemplate(): "+attachment2.getTemplate());
							resp.getWriter().println("Attachment2.getFileKey(): "+attachment2.getFileKey());
						}
					}

					
					if (attachment2 != null) {
						
						ImagesService imagesService = ImagesServiceFactory.getImagesService();

				        Image oldImage = ImagesServiceFactory.makeImageFromBlob(new BlobKey(attachment2.getFileKey()));
				        Transform resize = ImagesServiceFactory.makeResize(1600, 1600);
				        int size = Integer.parseInt(matcher.group(3));
				        if(size <= 1600) {
				        	if("h".equals(matcher.group(2))) {
				        		resize = ImagesServiceFactory.makeResize(1600, size);
				        	} else if("w".equals(matcher.group(2))) {
				        		resize = ImagesServiceFactory.makeResize(size, 1600);
				        	} else if("s".equals(matcher.group(2))) {
				        		resize = ImagesServiceFactory.makeResize(size, size);
				        	}
				        }

				        Image newImage = imagesService.applyTransform(resize, oldImage);
				        if(debug) {
							resp.getWriter().println("oldImage: "+oldImage);
							resp.getWriter().println("resize: "+resize);
							resp.getWriter().println("newImage: "+newImage);
				        }
				        
				        byte[] newImageData = newImage.getImageData();

				        if(!debug) {
							resp.setContentType("image/jpeg");
							resp.getOutputStream().write(newImageData);
				        }

						return;
					}
				}

			}
		}
		if (page == null || page.getTemplate() == null) {
			page = pageDao.findByUrl("404");
			if (page == null || page.getTemplate() == null) {
				resp.sendError(HttpServletResponse.SC_NOT_FOUND);
				return;
			}
			
			resp.setStatus(HttpServletResponse.SC_NOT_FOUND);

			resp.setContentType((page.getTemplate().getContentType() == null || page.getTemplate()
					.getContentType().isEmpty()) ? "text/html; charset=utf-8" : page.getTemplate()
					.getContentType());

			context.put("page", page);

			Velocity.evaluate(context, resp.getWriter(), "log tag name", page.getTemplate()
					.getHtmlAsString());

			return;
		}

		resp.setContentType((page.getTemplate().getContentType() == null || page.getTemplate()
				.getContentType().isEmpty()) ? "text/html; charset=utf-8" : page.getTemplate()
				.getContentType());

		context.put("page", page);

		Velocity.evaluate(context, resp.getWriter(), "log tag name", page.getTemplate()
				.getHtmlAsString());

	}

}
